package cn.harry.cabinet.server.routes

import cn.harry.cabinet.repository.OperationLogRepository
import cn.harry.cabinet.server.dto.common.ApiResponse
import cn.harry.cabinet.server.dto.common.PaginationInfo
import cn.harry.cabinet.server.dto.common.PaginationResponse
import cn.harry.cabinet.server.dto.operationlog.OperationLogQueryRequest
import cn.harry.cabinet.server.dto.operationlog.OperationLogResponse
import io.ktor.http.HttpStatusCode
import io.ktor.server.application.call
import io.ktor.server.request.receive
import io.ktor.server.response.respond
import io.ktor.server.routing.Route
import io.ktor.server.routing.get
import io.ktor.server.routing.post
import io.ktor.server.routing.route
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.serialization.InternalSerializationApi

/**
 * 操作日志API路由
 * 提供操作日志的查询接口
 */
@OptIn(InternalSerializationApi::class)
fun Route.operationLogRoutes(operationLogRepository: OperationLogRepository) {

    route("/api/operation-logs") {

        // 获取所有日志（不推荐，数据量大时使用分页接口）
        get("/all") {
            try {
                withContext(Dispatchers.IO) {
                    val logs = operationLogRepository.getAll()
                    val logResponses = OperationLogResponse.fromOperationLogList(logs)

                    call.respond(
                        HttpStatusCode.OK,
                        ApiResponse.success(logResponses, "获取所有日志成功")
                    )
                }
            } catch (e: Exception) {
                call.respondError("获取所有日志失败", e)
            }
        }


        // 分页查询日志
        get {
            try {
                val page = call.request.queryParameters["page"]?.toIntOrNull() ?: 1
                val size = call.request.queryParameters["size"]?.toIntOrNull() ?: 20

                // 验证分页参数
                if (page <= 0 || size <= 0 || size > 100) {
                    call.respondBadRequest("分页参数无效：页码必须大于0，每页大小必须在1-100之间")
                    return@get
                }

                withContext(Dispatchers.IO) {
                    // 计算偏移量
                    val offset = (page - 1) * size

                    // 获取总数
                    val totalCount = operationLogRepository.getCount().toLong()

                    // 获取分页数据
                    val logs = operationLogRepository.getPagedLogs(size, offset)
                    val logResponses = OperationLogResponse.fromOperationLogList(logs)

                    // 计算总页数
                    val totalPages = if (totalCount == 0L) 0L else (totalCount + size - 1) / size

                    // 构建分页响应
                    val paginationInfo = PaginationInfo(
                        page = page,
                        size = size,
                        total = totalCount,
                        totalPages = totalPages
                    )

                    val paginationResponse = PaginationResponse(
                        data = logResponses,
                        pagination = paginationInfo
                    )

                    call.respond(
                        HttpStatusCode.OK,
                        ApiResponse.success(paginationResponse, "分页查询日志成功")
                    )
                }
            } catch (e: Exception) {
                call.respondError("分页查询日志失败", e)
            }
        }

        // 按条件查询日志（POST方式，支持复杂查询）
        post("/search") {
            try {
                val request = call.receive<OperationLogQueryRequest>()

                // 验证分页参数
                if (!request.isValidPagination()) {
                    call.respondBadRequest("分页参数无效：页码必须大于0，每页大小必须在1-100之间")
                    return@post
                }

                // 验证时间范围
                if (!request.isValidTimeRange()) {
                    call.respondBadRequest("时间范围无效：开始时间不能晚于结束时间")
                    return@post
                }

                withContext(Dispatchers.IO) {
                    val offset = request.getOffset()

                    // 使用复合查询
                    val logs = operationLogRepository.searchLogs(
                        type = request.operationType,
                        result = request.result,
                        operatorId = request.operatorId,
                        startTime = request.startTime,
                        endTime = request.endTime,
                        limit = request.size,
                        offset = offset
                    )

                    val logResponses = OperationLogResponse.fromOperationLogList(logs)

                    // 注意：这里简化处理，实际应该根据查询条件计算总数
                    // 可以在DAO中添加对应的count查询方法
                    val totalCount = operationLogRepository.getCount().toLong()
                    val totalPages = if (totalCount == 0L) 0L else (totalCount + request.size - 1) / request.size

                    val paginationInfo = PaginationInfo(
                        page = request.page,
                        size = request.size,
                        total = totalCount,
                        totalPages = totalPages
                    )

                    val paginationResponse = PaginationResponse(
                        data = logResponses,
                        pagination = paginationInfo
                    )

                    call.respond(
                        HttpStatusCode.OK,
                        ApiResponse.success(paginationResponse, "条件查询日志成功")
                    )
                }
            } catch (e: Exception) {
                call.respondError("条件查询日志失败", e)
            }
        }
    }
}

/**
 * 私有扩展函数：响应错误请求
 */
@OptIn(InternalSerializationApi::class)
private suspend fun io.ktor.server.application.ApplicationCall.respondBadRequest(message: String) {
    respond(
        HttpStatusCode.BadRequest,
        ApiResponse.errorResponse(400, message)
    )
}

/**
 * 私有扩展函数：响应未找到错误
 */
@OptIn(InternalSerializationApi::class)
private suspend fun io.ktor.server.application.ApplicationCall.respondNotFound(message: String) {
    respond(
        HttpStatusCode.NotFound,
        ApiResponse.errorResponse(404, message)
    )
}

/**
 * 私有扩展函数：响应服务器错误
 */
@OptIn(InternalSerializationApi::class)
private suspend fun io.ktor.server.application.ApplicationCall.respondError(message: String, exception: Exception) {
    println("$message: ${exception.javaClass.simpleName} - ${exception.message}")
    exception.printStackTrace()

    respond(
        HttpStatusCode.InternalServerError,
        ApiResponse.errorResponse(500, "$message: ${exception.message}")
    )
}
